package org.fastsyncer.manager.util;

import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.fastsyncer.common.constant.ConnectorConstant;
import org.fastsyncer.common.entity.MappingTask;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public abstract class CleanUtil {

    public static void clean(MappingTask task, JSONObject t) throws Exception {
        Map<String, List<Map<String, String>>> query = task.getQuery();
        if (query == null || query.isEmpty()) {
            return;
        }
        // 解析And/Or过滤条件
        List<Map<String, String>> addList = query.get(ConnectorConstant.OPERTION_QUERY_AND);
        List<Map<String, String>> orList = query.get(ConnectorConstant.OPERTION_QUERY_OR);
        //没有过滤条件时直接跳过数据清洗环节
        if (addList.isEmpty() && orList.isEmpty()) {
            return;
        }

        // 清洗数据
        JSONArray clear = new JSONArray();
        JSONArray array = t.getJSONArray("msg");
        int len = array.length();
        for (int i = 0; i < len; i++) {
            JSONObject obj = array.getJSONObject(i);
            //如果是删除操作
            JSONArray d = null;
            if (StringUtils.equals(ConnectorConstant.OPERTION_DELETE, obj.getString("eventType"))) {
                d = obj.getJSONArray("before");
            } else {
                //如果是新增、修改操作
                d = obj.getJSONArray("after");
            }
            if (d == null) {
                continue;
            }

            // 如果或条件不为空，并且满足或条件时,将同步数据放入result
            if (!orList.isEmpty() && parseOrCondition(orList, d)) {
                clear.put(obj);
                //已经满足or条件
                continue;
            }

            if (!addList.isEmpty() && parseAndCondition(addList, d)) {
                clear.put(obj);
            }
        }
        t.put("msg", clear);
    }

    /**
     * @param andList 表达式
     * @param row 验证数据
     * @return
     * @throws JSONException 
     */
    private static boolean parseAndCondition(List<Map<String, String>> andList, JSONArray row) throws JSONException {
        boolean r = false;
        // 思路：遍历条件,一个条件对应row中对应col的值,只有满足所有条件才返回true
        int rLen = row.length();
        for (Map<String, String> map : andList) {
            String oprName = map.get("name");
            String opr = map.get("operator");
            String oprValue = map.get("value");
            for (int i = 0; i < rLen; i++) {
                JSONObject col = row.getJSONObject(i);
                // 一个条件对应row中对应col的值
                if (oprName.equals(col.getString("name"))) {
                    r = isAualified(opr, oprValue, col.getString("value"));
                    break;
                }
            }

            // 只要其中任一个条件不通过,直接返回false
            if (!r) {
                break;
            }
        }
        return r;
    }

    /**
     * @param orList 表达式
     * @param row 验证数据
     * @return
     * @throws JSONException 
     */
    private static boolean parseOrCondition(List<Map<String, String>> orList, JSONArray row) throws JSONException {
        boolean r = false;
        // 思路：遍历条件,一个条件对应row中对应col的值,只要满足任一条件就返回true
        int rLen = row.length();
        for (Map<String, String> map : orList) {
            String oprName = map.get("name");
            String opr = map.get("operator");
            String oprValue = map.get("value");
            for (int i = 0; i < rLen; i++) {
                JSONObject col = row.getJSONObject(i);
                // 一个条件对应row中对应col的值
                if (oprName.equals(col.getString("name"))) {
                    r = isAualified(opr, oprValue, col.getString("value"));
                    break;
                }
            }

            // 只要其中任一个条件不通过,直接返回false
            if (r) {
                break;
            }
        }
        return r;
    }

    /**
     * @param opr 公式
     * @param p1 条件值
     * @param p2 同步值
     * @return 运算结果
     */
    private static boolean isAualified(String opr, String p1, String p2) {
        boolean r = false;
        switch (opr) {
        case "equal":
            r = p1.equals(p2);
            break;
        case "notEqual":
            r = !p1.equals(p2);
            break;
        case "gt":
            // age > 10
            if (StringUtils.isNumeric(p1) && StringUtils.isNumeric(p2)) {
                r = Integer.parseInt(p1) < Integer.parseInt(p2);
            }
            break;
        case "lt":
            if (StringUtils.isNumeric(p1) && StringUtils.isNumeric(p2)) {
                r = Integer.parseInt(p1) > Integer.parseInt(p2);
            }
            break;
        case "ltAndEqual":
            // age >= 10
            if (StringUtils.isNumeric(p1) && StringUtils.isNumeric(p2)) {
                r = Integer.parseInt(p1) <= Integer.parseInt(p2);
            }
            break;
        case "gtAndEqual":
            if (StringUtils.isNumeric(p1) && StringUtils.isNumeric(p2)) {
                r = Integer.parseInt(p1) >= Integer.parseInt(p2);
            }
            break;
        default:
            break;
        }
        return r;
    }
    
}
